package com.cloud.lawcase.api.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.cloud.lawcase.api.bean.LawItemSearchCriteria;
import com.cloud.lawcase.api.entity.*;
import com.cloud.lawcase.api.mapper.*;
import com.cloud.lawcase.common.openapi.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cloud.lawcase.api.bean.LawSearchCriteria;
import com.cloud.lawcase.api.service.OpenApiService;
import com.cloud.lawcase.common.exception.BizException;
import com.cloud.lawcase.common.utils.DateHelper;
import com.cloud.lawcase.common.utils.JwtTokenHelper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import static com.netflix.config.DeploymentContext.ContextKey.appId;

@Service
@Transactional
public class OpenApiServiceImpl implements OpenApiService {

    @Autowired
    private TcAccessTokenMapper tcAccessTokenMapper;

    @Autowired
    private TcAccessGlobalParamsMapper tcAccessGlobalParamsMapper;

    @Autowired
    private TcDicLawMapper tcDicLawMapper;

    @Autowired
    private TcDicLawGroupMapper tcDicLawGroupMapper;

    @Autowired
    private TcDicLawItemMapper tcDicLawItemMapper;

    @Autowired
    private TcDicLawCauseMapper tcDicLawCauseMapper;

    @Autowired
    private TcLawClDetailMapper tcLawClDetailMapper;

    @Autowired
    private TcDicUnitFuncMapper tcDicUnitFuncMapper;

    @Autowired
    private TcDicUnitFuncLevelMapper tcDicUnitFuncLevelMapper;


    @Override
    public String refreshToken(String appId) {
        TcAccessToken token = tcAccessTokenMapper.selectByPrimaryKey(appId);
        if (null == token) {
            throw new BizException("无效的APPID");
        }
        Date now = new Date();
        if (token.getUpdateTime().before(DateHelper.getDateBegin(now))) {
            token.setUsedRefreshTimes(0);
        }
        if (now.before(token.getEnableDate())) {
            throw new BizException("APPID尚未启用");
        }
        if (null == token.getUsedRefreshTimes()) {
            token.setUsedRefreshTimes(0);
        } else {
            token.setUsedRefreshTimes(token.getUsedRefreshTimes() + 1);
        }
        if (token.getUsedRefreshTimes() >= token.getRefreshTimes()) {
            // 当天刷新超过指定次数，不允许再进行获取token操作（防止恶意攻击）
            throw new BizException("当日刷新次数超过上限");
        }
        tcAccessTokenMapper.updateByPrimaryKey(token);
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("APPID", appId);
        Date expireDate = DateHelper.getDateBeforeOrAfterMinutes(now, token.getTokenValidity());
        return JwtTokenHelper.generateToken(claims, expireDate);
    }

    @Override
    public PageInfo<OpenApiLawBean> listLaw(LawSearchCriteria criteria) {
        criteria.setRegions(this.loadRegionParam(criteria.getAppId()));
        return PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize()).doSelectPageInfo(() -> {
            tcDicLawMapper.searchExotericLaw(criteria);
        });
    }

    @Override
    public PageInfo<OpenApiLawCauseBean> listCause(OpenApiLawCauseSearchCriteria criteria) {
        criteria.setRegions(this.loadRegionParam(criteria.getAppId()));
        PageInfo<OpenApiLawCauseBean> causePage = PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize())
                .doSelectPageInfo(() -> {
                    tcDicLawCauseMapper.searchExotericLawCause(criteria);
                });
        List<OpenApiLawCauseBean> causeList = causePage.getList();
        List<Long> causeIds = new ArrayList<Long>();
        List<Long> causeItemIds = new ArrayList<Long>();
        for (OpenApiLawCauseBean c : causeList) {
            causeIds.add(c.getCauseId());
            causeItemIds.add(c.getPunishItemId());
        }
        // 罚则
        List<OpenApiLawCauseItemBean> punishItems = tcDicLawItemMapper.listPunishItems(causeItemIds);
        // 违则、依据
        List<OpenApiLawCauseItemBean> basisItems = tcDicLawItemMapper.listCausesItems(causeIds);
        for (OpenApiLawCauseBean cause : causeList) {
            for (OpenApiLawCauseItemBean punishItem : punishItems) {
                if (punishItem.getItemId().equals(cause.getPunishItemId())) {
                    cause.setPunishBasis(punishItem);
                    break;
                }
            }
            for (OpenApiLawCauseItemBean basisItem : basisItems) {
                if (basisItem.getCauseId().equals(cause.getCauseId())) {
                    if (1 == basisItem.getItemTypeId()) {// 违则
                        cause.getInfringeBasis().add(basisItem);
                    } else if (10 == basisItem.getItemTypeId()) {// 准用依据
                        cause.getPermitBasis().add(basisItem);
                    } else if (basisItem.getItemTypeId() >= 4 && basisItem.getItemTypeId() <= 8) {
                        cause.getOtherBasis().add(basisItem);
                    }
                }
            }
        }
        return causePage;
    }

    @Override
    public List<OpenApiLawCauseStackBean> listCauseStack(OpenApiCauseStackSearchCriteria criteria) {
        criteria.setRegions(this.loadRegionParam(criteria.getAppId()));
        List<OpenApiLawCauseStackBean> stacks = tcDicLawCauseMapper.listLawCauseStack(criteria);
        for (OpenApiLawCauseStackBean stack : stacks) {
            List<OpenApiLawCauseClBean> cl = tcLawClDetailMapper.listCLDetailByPunishId(stack.getPunishId());
            stack.setDetails(cl);
        }
        return stacks;
    }

    private String[] loadRegionParam(String appId) {
        Example paramExample = new Example(TcAccessGlobalParams.class);
        Criteria paramCriteria = paramExample.createCriteria();
        paramCriteria.andEqualTo("paramName", "law_region_id");
        paramCriteria.andEqualTo("appId", appId);
        List<TcAccessGlobalParams> params = tcAccessGlobalParamsMapper.selectByExample(paramExample);
        if (null != params && params.size() == 1) {
            return params.get(0).getParamValue().split(",");
        }
        return null;
    }

    @Override
    public List<TcDicUnitFunc> listUnitFunction() {
        List<TcDicUnitFunc> tcDicUnitFuncs = tcDicUnitFuncMapper.selectAll();
        return tcDicUnitFuncs;
    }

    @Override
    public List<TcDicUnitFuncLevel> listUnitFunctionLevel() {
        List<TcDicUnitFuncLevel> tcDicUnitFuncLevels = tcDicUnitFuncLevelMapper.selectAll();
        return tcDicUnitFuncLevels;
    }


    @Override
    public List<TcDicLawItem> listLawItem(LawItemSearchCriteria criteria) {
        List<TcDicLawItem> tcDicLawItems = tcDicLawItemMapper.listLawItem(criteria);
        return tcDicLawItems;
    }

    @Override
    public List<TcDicLawGroup> getLawGroup() {
        Example paramExample = new Example(TcDicLawGroup.class);
        Criteria paramCriteria = paramExample.createCriteria();
        paramCriteria.andLessThanOrEqualTo("seniorGroupId", 1);
        List<TcDicLawGroup> tcDicLawGroups = tcDicLawGroupMapper.selectByExample(paramExample);
        return tcDicLawGroups;
    }
}
